﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace katOS
{
    /// <summary>
    /// Class that acts as a parser from the user inputs
    /// </summary>
    class Parser
    {
        String[,] Symbols_table;

        /// <summary>
        /// Method that returns the instruction set from determined process
        /// </summary>
        /// <param name="process">The process from we get the instruction set</param>
        /// <param name="filename">The name that has the phisical instruction set</param>
        /// <returns></returns>
        public LinkedList<String> getInstructionSet(Process process, string filename) 
        {
            filename = "C:/Users/kareAndy/Documents/UVG/Ciclo 5/CC3002 Sistemas Operativos/Proyecto No. 1/katOSFiles/" + process.getFileName()+ ".txt";
            StreamReader read_file;
            bool correct = true;
            string input;

            try
            {
                read_file = File.OpenText(filename);
                input = read_file.ReadLine();
            }
            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
                correct = false;
                input = null;
                read_file = null;
            }
            if (correct)
            {
                LinkedList<String> instructions = new LinkedList<string>();
                while (input != null)
                {
                    while (input.Contains("  "))
                        input = input.Replace("  ", " ");
                    input = input.TrimEnd(' ');
                    input = input.TrimStart(' ');

                    //Remove_Spaces(input);
                    instructions.AddLast(input);
                    input = read_file.ReadLine();
                }
                read_file.Close();
                
                //TO REMOVE COMMENTS AND EMPTY LINES
                for (int i = 0; i < instructions.Count; i++)
                {
                    if (instructions.ElementAt(i).StartsWith(";"))
                    {
                        instructions.Remove(instructions.ElementAt(i));
                    }
                }

                for (int i = 0; i < instructions.Count; i++)
                {
                    if (instructions.ElementAt(i).CompareTo("") == 0)
                    {
                        instructions.Remove(instructions.ElementAt(i));
                    }
                }

                SymbolsTable(process, instructions);
                process.setSymbolsTable(Symbols_table);
                //REMOVE THIS IS FOR CHECK ONLY
                /*Console.WriteLine("the instructions are: ");
                for (int i = 0; i < instructions.Count; i++)
                    Console.WriteLine(instructions.ElementAt(i));
                Console.WriteLine("leaving parser");*/

                return instructions;
            }
            return null;
        }

        /// <summary>
        /// Method that removes unnecessary spaces from the instruction set
        /// </summary>
        /// <param name="instructionp">The instruction to be checked</param>
        /// <returns>The instruction with unnecessary spaces removed</returns>
        private String Remove_Spaces(string instructionp)
        {
            string inst;
            inst = instructionp.TrimEnd(' ');
            inst = inst.TrimStart(' ');

            while (instructionp.Contains("  "))
                instructionp = instructionp.Replace("  ", " ");
            while (instructionp.Contains("\t"))
                instructionp = instructionp.Replace("\t", " ");
            return instructionp;
        }

        /// <summary>
        /// Method that creates the symbols table for the instruction set
        /// </summary>
        /// <param name="process">The process to which the symbol table belongs</param>
        /// <param name="instructions">The instruction set</param>
        public void SymbolsTable(Process process, LinkedList<String> instructions)
        {
            LinkedList<String> tags = new LinkedList<String>();
            LinkedList<String> tag_line = new LinkedList<String>();

            for (int i = 0; i < instructions.Count; i++)
            {
                String temp = instructions.ElementAt(i);

                if (temp.StartsWith("'") && temp.EndsWith("'"))
                {
                    String a_tag = temp.Substring(1, temp.Length - 2);
                    if (a_tag.Contains(" ") == false)
                    {
                        tags.AddLast(a_tag);
                        tag_line.AddLast(i+"");
                        instructions.Remove(instructions.ElementAt(i));
                    }
                    else
                    {
                        Console.WriteLine("Wrong tag definition at line " + tag_line.ElementAt(i));
                    }
                }
            }
            Symbols_table = new String[tags.Count, 2];

            for (int i = 0; i < tags.Count; i++)
            {
                Symbols_table[i,0] = (tags.ElementAt(i));
                Symbols_table[i,1] = (tag_line.ElementAt(i));
            }
            //TO CHECK ONLY REMOVE WHEN FINISHED
            /*Console.WriteLine("the length of this thing is: "+Symbols_table.Length);
            for (int i = 0; i < tags.Count; i++)
            {
                Console.Write(Symbols_table[i, 0]+" ");
                Console.WriteLine(Symbols_table[i,1]);
            }
            process.setSymbolsTable(Symbols_table);*/
        }

        /// <summary>
        /// Mehtod that returns the symbols table
        /// </summary>
        /// <returns>The symbols table from determined process</returns>
        public String[,] getSymbolsTable()
        {
            return Symbols_table;
        }
    }
}
